package cn.caplike.demo.repository.java.reflect;


import com.esotericsoftware.reflectasm.ConstructorAccess;
import com.esotericsoftware.reflectasm.FieldAccess;
import com.esotericsoftware.reflectasm.MethodAccess;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * ReflectASM
 *
 * @author LiKe
 * @date 2019-11-13 12:59
 */
public class ReflectASM {

    private final int loop = 1000000000;

    public static void main(String[] args) throws Exception {
        ReflectASM test = new ReflectASM();
        test.testJdkReflect();
        test.testReflectAsm4Name();
        test.testReflectAsm4Index();
    }

    /**
     * JDK反射调用方法
     */
    private void testJdkReflect() throws Exception {
        Sample target = new Sample();
        long start = System.currentTimeMillis();
        Method method = target.getClass().getMethod("update", int.class, String.class);
        for (int i = 0; i < loop; i++) {
            method.invoke(target, 1, "caplike");
        }
        long end = System.currentTimeMillis();
        System.out.println("jdk-reflect time spent: " + new BigDecimal(end - start).divide(new BigDecimal(1000), 3, RoundingMode.HALF_UP));
    }

    /**
     * ReflectAsm反射调用方法
     * 用名称定位反射方法
     */
    private void testReflectAsm4Name() {
        Sample target = new Sample();
        MethodAccess access = MethodAccess.get(Sample.class);//生成字节码的方式创建UserServiceMethodAccess
        long start = System.currentTimeMillis();
        for (int i = 0; i < loop; i++) {
            access.invoke(target, "update", 1, "caplike");
        }
        long end = System.currentTimeMillis();
        System.out.println("asm-reflect-name time spent: " + new BigDecimal(end - start).divide(new BigDecimal(1000), 3, RoundingMode.HALF_UP));
    }

    /**
     * ReflectAsm反射调用方法
     * 用方法和字段的索引定位反射方法，性能高
     */
    private void testReflectAsm4Index() {
        Sample target = new Sample();
        MethodAccess access = MethodAccess.get(Sample.class);
        int index = access.getIndex("update", int.class, String.class);
        long start = System.currentTimeMillis();
        for (int i = 0; i < loop; i++) {
            access.invoke(target, index, 1, "caplike");
        }
        long end = System.currentTimeMillis();
        System.out.println("asm-reflect-index time spent: " + new BigDecimal(end - start).divide(new BigDecimal(1000), 3, RoundingMode.HALF_UP));
    }

    /**
     * ReflectAsm反射来set/get字段值
     */
    public void testFieldAccess() {
        Sample target = new Sample();
        FieldAccess fieldAccess = FieldAccess.get(target.getClass());
        fieldAccess.set(target, "state", 1);
        int state = (Integer) fieldAccess.get(target, "state");
        System.out.println(state);
    }

    /**
     * ReflectAsm反射来调用构造方法
     */
    public void testConstructorAccess() {
        ConstructorAccess<Sample> constructorAccess = ConstructorAccess.get(Sample.class);
        Sample sample = constructorAccess.newInstance();
        System.out.println(sample);
    }

    /**
     * 查找方法的索引
     */
    public void testIndex() {
        Sample target = new Sample();
        MethodAccess methodAccess = MethodAccess.get(target.getClass());
        int index = methodAccess.getIndex("update", int.class, String.class);
        System.out.println(index);
    }

}